package com.znf4.core;

import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.znf4.App;
import com.znf4.entity.PollingParam;
import com.znf4.exception.BizException;
import com.znf4.notify.entity.RpNotifyRecord;
import com.znf4.notify.enums.NotifyStatusEnum;
import com.znf4.notify.enums.NotifyTypeEnum;
import com.znf4.utils.DateUtils;

/**
 * <b>功能说明:轮询任务
 */
public class PollingTask implements Runnable, Delayed {
    private static final Logger LOG = LoggerFactory.getLogger(PollingTask.class);

    private long executeTime;

    private RpNotifyRecord notifyRecord;

    private PollingQueue pollingQueue;

    private PollingParam pollingParam;

    private PollingPersist pollingPersist = App.pollingPersist;

    public PollingTask() {
    }

    public PollingTask(RpNotifyRecord notifyRecord, PollingQueue pollingQueue, PollingParam pollingParam) {
        super();
        this.notifyRecord = notifyRecord;
        this.pollingQueue = pollingQueue;
        this.pollingParam = pollingParam;
        this.executeTime = getExecuteTime(notifyRecord);
    }

    /**
     * 计算任务允许执行的开始时间(executeTime).<br/>
     *
     * @param record
     * @return
     */
    private long getExecuteTime(RpNotifyRecord record) {
        long lastNotifyTime = record.getLastNotifyTime().getTime(); // 最后通知时间（上次通知时间）
        Integer notifyTimes = record.getNotifyTimes(); // 已通知次数
        LOG.info("===>pollingTimes:{}",notifyTimes);
        //Integer nextNotifyTimeInterval = pollingParam.getNotifyParams().get(notifyTimes + 1); // 当前发送次数对应的时间间隔数（分钟数）
        Integer nextNotifyTimeInterval = record.getNotifyRuleMap().get(String.valueOf(notifyTimes + 1)); // 当前发送次数对应的时间间隔数（分钟数）
        long nextNotifyTime = (nextNotifyTimeInterval == null ? 0 : nextNotifyTimeInterval * 60 * 1000) + lastNotifyTime;
        LOG.info("===>notify id:{}, nextNotifyTime:{}" ,record.getId() , DateUtils.formatDate(new Date(nextNotifyTime), "yyyy-MM-dd HH:mm:ss SSS"));
        return nextNotifyTime;
    }

    /**
     * 比较当前时间(task.executeTime)与任务允许执行的开始时间(executeTime).<br/>
     * 如果当前时间到了或超过任务允许执行的开始时间，那么就返回-1，可以执行。
     */
    public int compareTo(Delayed o) {
        PollingTask task = (PollingTask) o;
        return executeTime > task.executeTime ? 1 : (executeTime < task.executeTime ? -1 : 0);
    }

    public long getDelay(TimeUnit unit) {
        return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    /**
     * 执行通知处理.
     */
    public void run() {
        Integer notifyTimes = notifyRecord.getNotifyTimes(); // 得到当前通知对象的通知次数
        Integer maxNotifyTimes = notifyRecord.getLimitNotifyTimes(); // 最大通知次数
        Date notifyTime = new Date(); // 本次通知的时间
        
      /*  if(notifyRecord.getNotifyType().equals(NotifyTypeEnum.PROXY_PAY.name())){//代付
        	LOG.info("===>proxy pay msg : {}, notify id:{}, notifyTimes:{}, notifyType:{}" ,notifyRecord.getUrl() ,notifyRecord.getId(),notifyTimes,notifyRecord.getNotifyType());
        	JSON json = (JSON) JSONObject.parse(notifyRecord.getUrl());
        	ProxyPayParam proxyPayParam = JSONObject.toJavaObject(json, ProxyPayParam.class);
        	pollingPersist.sendProxyPay(proxyPayParam, notifyRecord);
        	
        }else if(notifyRecord.getNotifyType().equals(NotifyTypeEnum.PROXY_PAY_RESULT_SEARCH.name())){
        	LOG.info("===>proxy pay query msg : {}, notify id:{}, notifyTimes:{}, notifyType:{}" ,notifyRecord.getUrl() ,notifyRecord.getId(),notifyTimes,notifyRecord.getNotifyType());
        	// 去通知
            try {
                JSON json = (JSON) JSONObject.parse(notifyRecord.getUrl());
                ProxyPayQueryParam proxyPayQueryParam = JSONObject.toJavaObject(json, ProxyPayQueryParam.class);
                pollingPersist.getProxyPayQueryResult(proxyPayQueryParam, notifyRecord);

            } catch (BizException e) {
                LOG.error("===>PollingTask", e);
            } catch (Exception e) {
                notifyRecord.setEditTime(notifyTime); // 取本次通知时间作为最后修改时间
                notifyRecord.setNotifyTimes(notifyTimes + 1); // 通知次数+1
                if (notifyRecord.getNotifyTimes() < maxNotifyTimes) {
                    // 判断是否超过重发次数，未超重发次数的，再次进入延迟发送队列
                    pollingQueue.addToNotifyTaskDelayQueue(notifyRecord);
                    pollingPersist.updateNotifyRord(notifyRecord.getId(), notifyRecord.getNotifyTimes(), NotifyStatusEnum.HTTP_REQUEST_SUCCESS.name(), notifyTime);
                    LOG.info("===>update NotifyRecord status to HTTP_REQUEST_SUCCESS, notifyId: {}" ,notifyRecord.getId());
                } else {
                    // 到达最大通知次数限制，标记为通知失败
                    pollingPersist.updateNotifyRord(notifyRecord.getId(), notifyRecord.getNotifyTimes(), NotifyStatusEnum.FAILED.name(), notifyTime);
                    LOG.info("===>update NotifyRecord status to failed, notifyId:{}", notifyRecord.getId());
                }
                // 异常
                LOG.error("===>PollingTask", e);
                pollingPersist.saveNotifyRecordLogs(notifyRecord.getId(), notifyRecord.getMerchantNo(), notifyRecord.getMerchantOrderNo(), notifyRecord.getUrl(), "", 0);
            }
        }else if(notifyRecord.getNotifyType().equals(NotifyTypeEnum.QUICK_PAY_RESULT_SEARCH.name())){
            LOG.info("===>quick pay query msg : {}, notify id:{}, notifyTimes:{}, notifyType:{}" ,notifyRecord.getUrl() ,notifyRecord.getId(),notifyTimes,notifyRecord.getNotifyType());
            // 去通知
            try {
                JSON json = (JSON) JSONObject.parse(notifyRecord.getUrl());
                QuickPayQueryParam quickPayQueryParam = JSONObject.toJavaObject(json, QuickPayQueryParam.class);
                pollingPersist.getQuickPayQueryResult(quickPayQueryParam, notifyRecord);

            } catch (BizException e) {
                LOG.error("===>PollingTask", e);
            } catch (Exception e) {
                notifyRecord.setEditTime(notifyTime); // 取本次通知时间作为最后修改时间
                notifyRecord.setNotifyTimes(notifyTimes + 1); // 通知次数+1
                if (notifyRecord.getNotifyTimes() < maxNotifyTimes) {
                    // 判断是否超过重发次数，未超重发次数的，再次进入延迟发送队列
                    pollingQueue.addToNotifyTaskDelayQueue(notifyRecord);
                    pollingPersist.updateNotifyRord(notifyRecord.getId(), notifyRecord.getNotifyTimes(), NotifyStatusEnum.HTTP_REQUEST_SUCCESS.name(), notifyTime);
                    LOG.info("===>update NotifyRecord status to HTTP_REQUEST_SUCCESS, notifyId: {}" ,notifyRecord.getId());
                } else {
                    // 到达最大通知次数限制，标记为通知失败
                    pollingPersist.updateNotifyRord(notifyRecord.getId(), notifyRecord.getNotifyTimes(), NotifyStatusEnum.FAILED.name(), notifyTime);
                    LOG.info("===>update NotifyRecord status to failed, notifyId:{}", notifyRecord.getId());
                }
                // 异常
                LOG.error("===>PollingTask", e);
                pollingPersist.saveNotifyRecordLogs(notifyRecord.getId(), notifyRecord.getMerchantNo(), notifyRecord.getMerchantOrderNo(), notifyRecord.getUrl(), "", 0);
            }
        }else if(notifyRecord.getNotifyType().equals(NotifyTypeEnum.DEDUCT_PAY_RESULT_SEARCH.name())){
            LOG.info("===>deduct pay query msg : {}, notify id:{}, notifyTimes:{}, notifyType:{}" ,notifyRecord.getUrl() ,notifyRecord.getId(),notifyTimes,notifyRecord.getNotifyType());
            // 去通知
            try {
                JSON json = (JSON) JSONObject.parse(notifyRecord.getUrl());
                DeductPayQueryParam deductPayQueryParam = JSONObject.toJavaObject(json, DeductPayQueryParam.class);
                pollingPersist.getDeductPayQueryResult(deductPayQueryParam, notifyRecord);

            } catch (BizException e) {
                LOG.error("===>PollingTask", e);
            } catch (Exception e) {
                notifyRecord.setEditTime(notifyTime); // 取本次通知时间作为最后修改时间
                notifyRecord.setNotifyTimes(notifyTimes + 1); // 通知次数+1
                if (notifyRecord.getNotifyTimes() < maxNotifyTimes) {
                    // 判断是否超过重发次数，未超重发次数的，再次进入延迟发送队列
                    pollingQueue.addToNotifyTaskDelayQueue(notifyRecord);
                    pollingPersist.updateNotifyRord(notifyRecord.getId(), notifyRecord.getNotifyTimes(), NotifyStatusEnum.HTTP_REQUEST_SUCCESS.name(), notifyTime);
                    LOG.info("===>update NotifyRecord status to HTTP_REQUEST_SUCCESS, notifyId: {}" ,notifyRecord.getId());
                } else {
                    // 到达最大通知次数限制，标记为通知失败
                    pollingPersist.updateNotifyRord(notifyRecord.getId(), notifyRecord.getNotifyTimes(), NotifyStatusEnum.FAILED.name(), notifyTime);
                    LOG.info("===>update NotifyRecord status to failed, notifyId:{}", notifyRecord.getId());
                }
                // 异常
                LOG.error("===>PollingTask", e);
                pollingPersist.saveNotifyRecordLogs(notifyRecord.getId(), notifyRecord.getMerchantNo(), notifyRecord.getMerchantOrderNo(), notifyRecord.getUrl(), "", 0);
            }
        }else{
            LOG.info("未知的业务类型");
//            getDeductPayQueryResult
        }*/
    }
}
